#include "channel-allocation.h"
#include "ns3/log.h"
#include "ns3/simulator.h"
#include "ns3/mobility-model.h"
#include <cmath>

namespace ns3 {

NS_LOG_COMPONENT_DEFINE("ChannelAllocation");

NS_OBJECT_ENSURE_REGISTERED(ChannelAllocation);

TypeId ChannelAllocation::GetTypeId() {
    static TypeId tid = TypeId("ns3::ChannelAllocation")
        .SetParent<Object>()
        .SetGroupName("SAGINIoV");
        // 移除构造器，因为这是一个抽象类
        // .AddConstructor<ChannelAllocation>();
    return tid;
}

ChannelAllocation::ChannelAllocation()
    : m_nodeManager(nullptr),
      m_dataCollector(nullptr),
      m_numChannels(10),
      m_allowSatelliteConnection(true),
      m_allowGroundStationConnection(true),
      m_realTimeLoggingEnabled(false),
      m_loggingFrequency(1)
{
    NS_LOG_FUNCTION(this);
}

ChannelAllocation::~ChannelAllocation()
{
    NS_LOG_FUNCTION(this);
    StopPeriodic();
}

void ChannelAllocation::SetNumberOfChannels(uint32_t channels)
{
    NS_LOG_FUNCTION(this << channels);
    m_numChannels = channels;
}

void ChannelAllocation::SetNodeManager(NodeManager* nodeManager)
{
    NS_LOG_FUNCTION(this << nodeManager);
    m_nodeManager = nodeManager;
}

void ChannelAllocation::SetDataCollector(DataCollector* dataCollector)
{
    NS_LOG_FUNCTION(this << dataCollector);
    m_dataCollector = dataCollector;
}

void ChannelAllocation::SetAllowSatelliteConnection(bool allow)
{
    NS_LOG_FUNCTION(this << allow);
    m_allowSatelliteConnection = allow;
}

void ChannelAllocation::SetAllowGroundStationConnection(bool allow)
{
    NS_LOG_FUNCTION(this << allow);
    m_allowGroundStationConnection = allow;
}

std::map<uint32_t, int> ChannelAllocation::GetCurrentAllocation() const
{
    return m_currentAllocation;
}

double ChannelAllocation::CalculateSINR(uint32_t nodeId, int channelId)
{
    NS_LOG_FUNCTION(this << nodeId << channelId);
    
    if (!m_nodeManager) {
        NS_LOG_ERROR("Node manager is not set");
        return 0.0;
    }
    
    // 获取发送方和接收方的节点
    Ptr<Node> vehicleNode = nullptr;
    Ptr<Node> stationNode = nullptr;
    NodeType stationType = GROUND_STATION;
    
    // 查找车辆节点
    NodeContainer vehicles = m_nodeManager->GetVehicleNodes();
    for (uint32_t i = 0; i < vehicles.GetN(); i++) {
        if (vehicles.Get(i)->GetId() == nodeId) {
            vehicleNode = vehicles.Get(i);
            break;
        }
    }
    
    if (!vehicleNode) {
        NS_LOG_WARN("Vehicle node not found for ID: " << nodeId);
        return 0.0;
    }
    
    // 根据信道ID确定连接的是地面站还是卫星
    NodeContainer groundStations = m_nodeManager->GetGroundStationNodes();
    NodeContainer satellites = m_nodeManager->GetSatelliteNodes();
    
    if (channelId < static_cast<int>(groundStations.GetN())) {
        stationNode = groundStations.Get(channelId);
        stationType = GROUND_STATION;
    } else {
        int satIndex = channelId - groundStations.GetN();
        if (satIndex < static_cast<int>(satellites.GetN())) {
            stationNode = satellites.Get(satIndex);
            stationType = SATELLITE;
        }
    }
    
    if (!stationNode) {
        NS_LOG_WARN("Station node not found for channel: " << channelId);
        return 0.0;
    }
    
    // 获取移动模型
    Ptr<MobilityModel> vehicleMobility = vehicleNode->GetObject<MobilityModel>();
    Ptr<MobilityModel> stationMobility = stationNode->GetObject<MobilityModel>();
    
    if (!vehicleMobility || !stationMobility) {
        NS_LOG_WARN("Mobility model not found");
        return 0.0;
    }
    
    // 获取当前距离 - 这是计算车辆和基站距离的关键位置
    double distance = vehicleMobility->GetDistanceFrom(stationMobility);
    
    // 发送功率(dBm) - 重新平衡地面站和卫星功率
    double txPower = 0.0;
    if (stationType == GROUND_STATION) {
        // 恢复更真实的地面站发射功率，不要过高
        if (distance < 500) {
            txPower = 36.0; // 从40.0降低到36.0
        } else if (distance < 1000) {
            txPower = 40.0; // 从43.0降低到40.0
        } else {
            txPower = 43.0; // 从46.0降低到43.0
        }
    } else {
        // 适当提高卫星发射功率
        int satIndex = channelId - m_nodeManager->GetGroundStationNodes().GetN();
        double satelliteAltitude = 0.0;
        
        if (satIndex % 3 == 0) {
            satelliteAltitude = 550.0; // LEO
            txPower = 59.0; // 保持59.0
            
            // 调整功率衰减因子
            double attenuationFactor = 0.98; // 保持0.98
            txPower *= attenuationFactor;
            
        } else if (satIndex % 3 == 1) {
            satelliteAltitude = 1200.0; // MEO
            txPower = 63.0; // 从62.0提高到63.0
            
            // 调整功率衰减因子
            double attenuationFactor = 0.97; // 保持0.97
            txPower *= attenuationFactor;
            
        } else {
            satelliteAltitude = 35786.0; // GEO
            txPower = 68.0; // 从66.0提高到68.0
            
            // 调整功率衰减因子
            double attenuationFactor = 0.96; // 从0.95提高到0.96
            txPower *= attenuationFactor;
        }
        
        // 根据轨道高度对功率进行额外调整
        double heightAdjustment = std::log10(satelliteAltitude) / 5.0; // 从6.0改为5.0以增加调整值
        txPower += heightAdjustment;
    }
    
    // 计算接收功率 = 发送功率 - 路径损耗
    double pathLoss = CalculatePathLoss(nodeId, channelId);
    double rxPower = txPower - pathLoss;
    
    // 计算干扰
    double interference = CalculateInterference(nodeId, channelId);
    
    // 噪声功率密度，降低卫星环境的噪声温度
    double k = 1.38e-23; // 玻尔兹曼常数
    double temperature = (stationType == GROUND_STATION) ? 290.0 : 150.0; // 卫星环境温度从260K降低到150K
    double noisePowerDensity = 10 * std::log10(k * temperature * 1000); // dBm/Hz
    
    // 带宽设置
    double bandwidth = (stationType == GROUND_STATION) ? 10e6 : 20e6; // Hz
    
    // 热噪声功率 = 噪声功率密度 + 10*log10(带宽)
    double thermalNoise = noisePowerDensity + 10 * std::log10(bandwidth);
    
    // 接收机噪声系数 - 更真实的性能比较
    double noiseFigure = (stationType == GROUND_STATION) ? 7.0 : 3.0; // 地面站从6.0提高到7.0，卫星保持3.0
    
    // 总噪声 = 热噪声 + 噪声系数
    double totalNoise = thermalNoise + noiseFigure;
    
    // 抗干扰和噪声处理能力 - 更好地平衡地面站和卫星能力
    if (stationType == GROUND_STATION) {
        interference -= 2.0; // 从2.5降低到2.0
        totalNoise -= 1.0; // 保持1.0
    } else {
        // 卫星链路抗干扰能力
        interference -= 6.0; // 从6.5降低到6.0
        totalNoise -= 3.5; // 从4.0降低到3.5
        
        // 限制信号增强程度
        if (rxPower - totalNoise < -50.0) {
            // 信号增强因子适当调整
            rxPower += 12.0; // 从15.0降低到12.0
        }
    }
    
    // 重新计算SINR，考虑改进的干扰和噪声处理
    double sinr = rxPower - (interference + totalNoise);
    
    // 按照节点类型调整SINR距离惩罚 - 地面站性能更严格受距离限制
    if (stationType == GROUND_STATION) {
        // 地面站的距离惩罚，使其覆盖范围更加有限
        if (distance > 1800) {
            sinr -= 10.0; // 从7.5提高到10.0，远距离严重衰减
        } else if (distance > 1200) {
            sinr -= 5.0; // 从4.0提高到5.0
        } else if (distance > 800) {
            sinr -= 3.0; // 从2.0提高到3.0
        }
    } else {
        // 调整卫星链路距离惩罚，使更远距离更具竞争力
        Vector vehiclePos = vehicleMobility->GetPosition();
        Vector satellitePos = stationMobility->GetPosition();
        double dx = satellitePos.x - vehiclePos.x;
        double dy = satellitePos.y - vehiclePos.y;
        double dz = satellitePos.z - vehiclePos.z;
        double horizontalDistance = std::sqrt(dx * dx + dy * dy);
        double elevationAngle = std::atan2(dz, horizontalDistance) * 180.0 / M_PI;
        
        // 根据仰角调整SINR - 减少惩罚值
        if (elevationAngle < 15) {
            sinr -= 4.0; // 从5.0降低到4.0
        } else if (elevationAngle < 30) {
            sinr -= 2.0; // 从2.5降低到2.0
        } else if (elevationAngle < 60) {
            sinr -= 0.8; // 从1.0降低到0.8
        } else {
            sinr -= 0.2; // 从0.3降低到0.2
        }
        
        // 为卫星链路添加适当的信号增强
        sinr += 8.0; // 从10.0降低到8.0
    }
    
    // 记录详细的计算过程以便调试
    NS_LOG_DEBUG("SINR计算详情: 节点=" << nodeId << ", 信道=" << channelId 
                << ", 类型=" << (stationType == GROUND_STATION ? "地面站" : "卫星")
                << ", 距离=" << distance << "m" 
                << ", 发送功率=" << txPower << "dBm"
                << ", 路径损耗=" << pathLoss << "dB"
                << ", 接收功率=" << rxPower << "dBm"
                << ", 干扰=" << interference << "dBm"
                << ", 噪声=" << totalNoise << "dBm"
                << ", SINR=" << sinr << "dB");
    
    return sinr;
}

// 实现更精确的干扰计算模型
double ChannelAllocation::CalculateInterference(uint32_t nodeId, int channelId)
{
  // 获取相关节点
  Ptr<Node> vehicleNode = GetVehicleNodeById(nodeId);
  Ptr<Node> channelNode = GetChannelNodeById(channelId);
  
  if (!vehicleNode || !channelNode)
  {
    return -91.9897; // 默认底噪，不应该直接返回这个值
  }
  
  // 获取移动模型
  Ptr<MobilityModel> vehicleMobility = vehicleNode->GetObject<MobilityModel>();
  Ptr<MobilityModel> channelMobility = channelNode->GetObject<MobilityModel>();
  
  if (!vehicleMobility || !channelMobility)
  {
    return -91.9897; // 默认底噪
  }
  
  // 确定节点类型
  NodeContainer groundStations = m_nodeManager->GetGroundStationNodes();
  bool isSatellite = (channelId >= static_cast<int>(groundStations.GetN()));
  
  // 计算噪声底线 (热噪声 + 设备噪声系数)
  double bandwidth_MHz = 20.0; // 20 MHz带宽
  double noiseFigure_dB = 9.0; // 设备噪声系数
  double thermalNoise_dBm = -174.0 + 10 * log10(bandwidth_MHz * 1e6); // 热噪声
  double noiseFloor_dBm = thermalNoise_dBm + noiseFigure_dB; // 约-91.9897 dBm
  
  // 获取当前所有活跃车辆的分配
  auto allocation = GetCurrentAllocation();
  
  // 获取当前时间点活跃的车辆数据
  double currentTime = Simulator::Now().GetSeconds();
  std::vector<VehicleData> vehicleData = m_nodeManager->GetVehicleDataAtTime(currentTime);
  
  // 获取车辆容器
  NodeContainer allVehicles = m_nodeManager->GetVehicleNodes();
  
  // 转换到线性功率值用于累加 (mW)
  double linearInterference_mW = pow(10.0, noiseFloor_dBm / 10.0);
  
  // 计算当前车辆的ID，用于排除自身
  uint32_t currentVehicleId = nodeId;
  
  // 计算来自其他车辆的干扰
  for (const auto& vehicle : vehicleData)
  {
    uint32_t interferingNodeId = 0;
    
    // 查找车辆ID对应的节点ID
    for (uint32_t i = 0; i < allVehicles.GetN(); i++)
    {
      std::string id = m_nodeManager->GetVehicleIdForNode(allVehicles.Get(i)->GetId());
      if (id == vehicle.id && allVehicles.Get(i)->GetId() != currentVehicleId) {
        interferingNodeId = allVehicles.Get(i)->GetId();
        break;
      }
    }
    
    // 如果没找到干扰车辆或是当前车辆自身，则跳过
    if (interferingNodeId == 0 || interferingNodeId == currentVehicleId) {
      continue;
    }
    
    // 检查干扰车辆是否分配了相同信道
    auto it = allocation.find(interferingNodeId);
    if (it == allocation.end() || it->second != channelId) {
      continue; // 未分配或不是同一信道，不会干扰
    }
    
    // 获取干扰车辆节点
    Ptr<Node> interferingNode = GetVehicleNodeById(interferingNodeId);
    if (!interferingNode) {
      continue;
    }
    
    // 获取干扰车辆的移动模型
    Ptr<MobilityModel> interferingMobility = interferingNode->GetObject<MobilityModel>();
    if (!interferingMobility) {
      continue;
    }
    
    // 计算干扰车辆到当前信道的距离
    double interferingDistance = channelMobility->GetDistanceFrom(interferingMobility);
    
    // 假设发射功率 (dBm)
    double txPower_dBm = 23.0; // 约200mW
    
    // 计算干扰源的路径损耗
    double interferingPathLoss = 0.0;
    
    if (isSatellite) {
      // 卫星链路 - 基于自由空间路径损耗
      double freq_GHz = 20.0; // Ka频段，20 GHz
      double fspl = 20 * log10(interferingDistance / 1000.0) + 20 * log10(freq_GHz * 1000) + 32.44;
      
      // 计算仰角
      Vector interferingPos = interferingMobility->GetPosition();
      Vector satPos = channelMobility->GetPosition();
      double dx = satPos.x - interferingPos.x;
      double dy = satPos.y - interferingPos.y;
      double dz = satPos.z - interferingPos.z;
      double horizontalDistance = sqrt(dx*dx + dy*dy);
      double elevationAngle = atan2(dz, horizontalDistance) * 180.0 / M_PI;
      
      // 大气损耗随仰角变化
      double atmosphericLoss = 0.0;
      if (elevationAngle > 10.0) {
        atmosphericLoss = 3.0; // 高仰角
      } else if (elevationAngle > 5.0) {
        atmosphericLoss = 6.0; // 中等仰角
      } else {
        atmosphericLoss = 12.0; // 低仰角
      }
      
      interferingPathLoss = fspl + atmosphericLoss;
    } else {
      // 地面站链路 - 使用城市宏蜂窝模型
      interferingPathLoss = 128.1 + 37.6 * log10(interferingDistance / 1000.0) + 20.0; // 包含阴影衰落
    }
    
    // 干扰功率 = 发射功率 - 路径损耗
    double interferingPower_dBm = txPower_dBm - interferingPathLoss;
    
    // 只有当干扰功率高于噪声底线才累加
    if (interferingPower_dBm > noiseFloor_dBm) {
      // 将干扰功率从dBm转为mW并累加
      linearInterference_mW += pow(10.0, interferingPower_dBm / 10.0);
    }
  }
  
  // 将线性功率值转回dBm
  double totalInterference_dBm = 10.0 * log10(linearInterference_mW);
  
  // 干扰值应在合理范围内
  totalInterference_dBm = std::max(noiseFloor_dBm, std::min(totalInterference_dBm, -60.0));
  
  return totalInterference_dBm;
}

// 修改路径损耗计算函数，进一步优化卫星路径损耗
double ChannelAllocation::CalculatePathLoss(uint32_t nodeId, int channelId)
{
  // 获取相关节点
  Ptr<Node> vehicleNode = GetVehicleNodeById(nodeId);
  Ptr<Node> channelNode = GetChannelNodeById(channelId);
  
  if (!vehicleNode || !channelNode)
  {
    return 250.0; // 兜底值，避免返回无效数据
  }
  
  // 获取移动模型
  Ptr<MobilityModel> vehicleMobility = vehicleNode->GetObject<MobilityModel>();
  Ptr<MobilityModel> channelMobility = channelNode->GetObject<MobilityModel>();
  
  if (!vehicleMobility || !channelMobility)
  {
    return 250.0;
  }
  
  // 计算3D距离
  double distance = vehicleMobility->GetDistanceFrom(channelMobility);
  
  // 确定节点类型
  NodeContainer groundStations = m_nodeManager->GetGroundStationNodes();
  // 修复类型比较问题，将 groundStations.GetN() 转换为 int 类型
  bool isSatellite = (channelId >= static_cast<int>(groundStations.GetN()));
  
  if (isSatellite)
  {
    // 针对卫星链路的改进路径损耗模型
    // 使用扩展的自由空间路径损耗模型，添加大气衰减
    // 假设Ka频段 - 20GHz
    double freq_GHz = 20.0; 
    
    // 自由空间路径损耗 FSPL = 20*log10(d) + 20*log10(f) + 32.44
    // 其中d为千米，f为MHz
    double fspl = 20 * log10(distance / 1000.0) + 20 * log10(freq_GHz * 1000) + 32.44;
    
    // 计算仰角
    Vector vehiclePos = vehicleMobility->GetPosition();
    Vector satellitePos = channelMobility->GetPosition();
    double dx = satellitePos.x - vehiclePos.x;
    double dy = satellitePos.y - vehiclePos.y;
    double dz = satellitePos.z - vehiclePos.z;
    double horizontalDistance = sqrt(dx * dx + dy * dy);
    double elevationAngle = atan2(dz, horizontalDistance) * 180.0 / M_PI;
    
    // 大气损耗 - 随仰角增加而减小
    double atmosphericLoss = 0.0;
    if (elevationAngle > 10.0) {
      // 高仰角，较小损耗
      atmosphericLoss = 3.0;
    } else if (elevationAngle > 5.0) {
      // 中等仰角
      atmosphericLoss = 6.0;
    } else {
      // 低仰角，较大损耗
      atmosphericLoss = 12.0;
    }
    
    // 雨衰减 - 简化模型
    double rainLoss = 0.0; // 晴天
    
    // 总路径损耗
    double totalLoss = fspl + atmosphericLoss + rainLoss;
    
    // 确保结果在合理范围内
    return std::min(std::max(totalLoss, 180.0), 220.0);
  } 
  else 
  {
    // 地面基站路径损耗
    // 使用标准的城市宏蜂窝模型(3GPP)
    // L = 128.1 + 37.6 * log10(d), d为千米
    double pathLoss = 128.1 + 37.6 * log10(distance / 1000.0);
    
    // 建筑物穿透损耗
    double penetrationLoss = 20.0;
    
    // 阴影衰落 - 简化
    double shadowingLoss = 8.0;
    
    // 总路径损耗
    double totalLoss = pathLoss + penetrationLoss + shadowingLoss;
    
    // 确保结果在合理范围内
    return std::min(std::max(totalLoss, 80.0), 180.0);
  }
}

void ChannelAllocation::StartPeriodic(Time interval)
{
    NS_LOG_FUNCTION(this << interval);
    
    StopPeriodic(); // 确保之前的事件被取消
    
    m_allocationInterval = interval;
    m_allocationEvent = Simulator::Schedule(m_allocationInterval, 
                                          &ChannelAllocation::PeriodicAllocation, 
                                          this);
}

void ChannelAllocation::StopPeriodic()
{
    NS_LOG_FUNCTION(this);
    
    // 修复：使用IsPending代替已弃用的IsRunning
    if (m_allocationEvent.IsPending()) {
        m_allocationEvent.Cancel();
    }
}

void ChannelAllocation::PeriodicAllocation()
{
    NS_LOG_FUNCTION(this);
    
    // 获取当前时间
    double currentTime = Simulator::Now().GetSeconds();
    NS_LOG_INFO("Performing channel allocation at time " << currentTime << "s");
    
    // 确保输出能直接显示到控制台
    std::cout << "执行信道分配，时间: " << currentTime << "秒" << std::endl;
    
    // 执行信道分配
    m_currentAllocation = AllocateChannels();
    NS_LOG_INFO("Allocation completed, " << m_currentAllocation.size() << " vehicles allocated to channels");
    
    // 遍历所有分配结果并输出距离信息 - 注释掉相关路径损耗计算部分，这会触发详细的距离日志
    for (const auto& [nodeId, channelId] : m_currentAllocation) {
        // 注释掉下面这行，因为它会触发详细的距离日志输出
        // CalculatePathLoss(nodeId, channelId);
        
        // 确定节点类型
        NodeContainer groundStations = m_nodeManager->GetGroundStationNodes();
        bool isGroundStation = channelId < static_cast<int>(groundStations.GetN());
        
        std::cout << "分配结果: 车辆(" << nodeId << ", ID=" << m_nodeManager->GetVehicleIdForNode(nodeId)
                 << ")分配到" << (isGroundStation ? "地面站" : "卫星") 
                 << "(" << channelId << ")" << std::endl;
    }
    
    // 获取当前时间点的车辆数据
    std::vector<VehicleData> vehicles = m_nodeManager->GetVehicleDataAtTime(currentTime);
    NS_LOG_INFO("Retrieved " << vehicles.size() << " active vehicles at current time");
    
    // 收集数据
    if (m_dataCollector) {
        int recordedResults = 0;
        
        for (const auto& [nodeId, channelId] : m_currentAllocation) {
            // 找到对应的车辆数据
            std::string vehicleId;
            double x = 0, y = 0, z = 0, speed = 0;
            
            // 查找车辆ID和数据
            auto vehicleIdIter = m_nodeManager->GetVehicleIdForNode(nodeId);
            if (!vehicleIdIter.empty()) {
                vehicleId = vehicleIdIter;
                
                // 查找车辆数据
                for (const auto& vehicle : vehicles) {
                    if (vehicle.id == vehicleId) {
                        x = vehicle.x;
                        y = vehicle.y;
                        z = 0.0; // SUMO中Z通常为0
                        speed = vehicle.speed;
                        break;
                    }
                }
            }
            
            // 确定连接的节点类型和ID
            uint32_t connectedNodeId = 0;
            NodeType connectedNodeType = GROUND_STATION; // 默认为地面站
            
            // 这里需要根据信道ID确定连接的是哪个节点 (基站或卫星)
            // 这是一个简化的例子，实际实现可能更复杂
            NodeContainer groundStations = m_nodeManager->GetGroundStationNodes();
            NodeContainer satellites = m_nodeManager->GetSatelliteNodes();
            
            if (channelId < static_cast<int>(groundStations.GetN())) {
                connectedNodeId = groundStations.Get(channelId)->GetId();
                connectedNodeType = GROUND_STATION;
            } else {
                int satIndex = channelId - groundStations.GetN();
                if (satIndex < static_cast<int>(satellites.GetN())) {
                    connectedNodeId = satellites.Get(satIndex)->GetId();
                    connectedNodeType = SATELLITE;
                }
            }
            
            // 计算SINR和其他网络指标
            double sinr = CalculateSINR(nodeId, channelId);
            double interference = CalculateInterference(nodeId, channelId);
            double pathLoss = CalculatePathLoss(nodeId, channelId);
            double throughput = CalculateThroughput(sinr, connectedNodeType);
            double delay = CalculateDelay(nodeId, channelId);
            
            // 创建结果结构
            ChannelAllocationResult result;
            result.nodeId = nodeId;
            result.vehicleId = vehicleId;
            result.time = currentTime;
            result.x = x;
            result.y = y;
            result.z = z;
            result.speed = speed;
            result.channelId = channelId;
            result.connectedNodeId = connectedNodeId;
            result.connectedNodeType = connectedNodeType;
            result.sinr = sinr;
            result.throughput = throughput;
            result.delay = delay;
            result.interference = interference;
            result.pathLoss = pathLoss;
            
            // 记录结果
            m_dataCollector->RecordAllocationResult(result);
            recordedResults++;
        }
        
        NS_LOG_INFO("Recorded " << recordedResults << " allocation results for time " << currentTime);
    } else {
        NS_LOG_WARN("Data collector not set, no results recorded!");
    }
    
    // 安排下一次分配
    m_allocationEvent = Simulator::Schedule(m_allocationInterval, 
                                           &ChannelAllocation::PeriodicAllocation, 
                                           this);
}

void ChannelAllocation::EnableRealTimeLogging(bool enable, int frequency)
{
    m_realTimeLoggingEnabled = enable;
    m_loggingFrequency = frequency;
    
    if (m_realTimeLoggingEnabled) {
        NS_LOG_INFO("Real-time channel allocation logging enabled with frequency: " << m_loggingFrequency << " seconds");
    }
}

void ChannelAllocation::DoAllocateChannels()
{
    // 调用子类实现的分配逻辑
    AllocateChannels();
    
    // 如果启用了实时日志，在分配后记录结果
    if (m_realTimeLoggingEnabled) {
        LogAllocationResults();
    }
}

// 添加新的方法：根据距离判断地面站连接是否可行
bool ChannelAllocation::IsGroundStationConnectionFeasible(double distance, double sinr)
{
    // 调试日志，查看判断条件
    NS_LOG_DEBUG("检查地面站连接可行性: 距离=" << distance << "m, SINR=" << sinr << "dB");
    
    // 设置更严格的SINR阈值和距离限制
    double sinrThreshold = -13.0; // 从-15.0提高到-13.0
    double distanceLimit = 2000.0; // 从2500.0降低到2000.0，严格限制地面站覆盖范围
    
    // 判断连接是否可行
    bool feasible = (sinr >= sinrThreshold) && (distance <= distanceLimit);
    
    // 记录判断结果
    NS_LOG_DEBUG("地面站连接判断结果: " << (feasible ? "可行" : "不可行") 
               << " (SINR阈值=" << sinrThreshold << "dB, 距离限制=" << distanceLimit << "m)");
    
    return feasible;
}

// 添加新的方法：根据仰角和SINR判断卫星连接是否可行
bool ChannelAllocation::IsSatelliteConnectionFeasible(double elevationAngle, double sinr)
{
    // 调试日志
    NS_LOG_DEBUG("检查卫星连接可行性: 仰角=" << elevationAngle << "°, SINR=" << sinr << "dB");
    
    // 放宽卫星的最低仰角要求和SINR阈值
    double minElevationAngle = 6.0; // 从8.0降低到6.0
    double sinrThreshold = -17.0; // 从-15.0降低到-17.0，放宽卫星SINR要求
    
    // 判断连接是否可行
    bool feasible = (sinr >= sinrThreshold) && (elevationAngle >= minElevationAngle);
    
    // 记录判断结果
    NS_LOG_DEBUG("卫星连接判断结果: " << (feasible ? "可行" : "不可行") 
               << " (SINR阈值=" << sinrThreshold << "dB, 最低仰角=" << minElevationAngle << "°)");
    
    return feasible;
}

Ptr<Node>
ChannelAllocation::GetVehicleNodeById(uint32_t nodeId)
{
  if (!m_nodeManager) {
    return nullptr;
  }
  
  NodeContainer vehicles = m_nodeManager->GetVehicleNodes();
  for (uint32_t i = 0; i < vehicles.GetN(); i++) {
    if (vehicles.Get(i)->GetId() == nodeId) {
      return vehicles.Get(i);
    }
  }
  
  return nullptr;
}

Ptr<Node>
ChannelAllocation::GetChannelNodeById(int channelId)
{
  if (!m_nodeManager || channelId < 0) {
    return nullptr;
  }
  
  NodeContainer groundStations = m_nodeManager->GetGroundStationNodes();
  NodeContainer satellites = m_nodeManager->GetSatelliteNodes();
  
  if (channelId < static_cast<int>(groundStations.GetN())) {
    // 地面站信道
    return groundStations.Get(channelId);
  } else {
    // 卫星信道
    int satelliteIndex = channelId - groundStations.GetN();
    if (satelliteIndex < static_cast<int>(satellites.GetN())) {
      return satellites.Get(satelliteIndex);
    }
  }
  
  return nullptr;
}

double
ChannelAllocation::CalculateThroughput(double sinr, NodeType nodeType)
{
  NS_LOG_FUNCTION(this << sinr << nodeType);
  
  // 基于SINR计算吞吐量
  // 使用Shannon容量公式的简化版本: C = B * log2(1 + SINR)
  // 频谱效率转换为吞吐量
  
  double bandwidth_MHz = 20.0; // 20 MHz带宽
  double spectralEfficiency = 0.0;
  
  // 将dB转换为线性值
  double sinr_linear = std::pow(10.0, sinr / 10.0);
  
  // 基于Shannon公式计算谱效率
  spectralEfficiency = std::log2(1.0 + sinr_linear);
  
  // 不同类型节点的吞吐量可能有不同的上限
  double maxSpectralEfficiency = 0.0;
  if (nodeType == GROUND_STATION) {
    maxSpectralEfficiency = 5.5; // 最高频谱效率，约对应64QAM 3/4编码
  } else if (nodeType == SATELLITE) {
    maxSpectralEfficiency = 5.3; // 卫星链路频谱效率稍低
  }
  
  // 限制在最大频谱效率范围内
  spectralEfficiency = std::min(spectralEfficiency, maxSpectralEfficiency);
  
  // 如果SINR低于阈值，设置为0
  if (sinr < -5.0) {
    spectralEfficiency = std::max(0.0, spectralEfficiency * (1.0 + sinr / 5.0));
  }
  
  // 将频谱效率转换为吞吐量 (Mbps)
  double throughput = bandwidth_MHz * spectralEfficiency;
  
  return throughput;
}

double
ChannelAllocation::CalculateDelay(uint32_t nodeId, int channelId)
{
  NS_LOG_FUNCTION(this << nodeId << channelId);
  
  // 获取节点
  Ptr<Node> vehicleNode = GetVehicleNodeById(nodeId);
  Ptr<Node> channelNode = GetChannelNodeById(channelId);
  
  if (!vehicleNode || !channelNode) {
    return 0.3; // 默认高延迟
  }
  
  // 获取移动模型
  Ptr<MobilityModel> vehicleMobility = vehicleNode->GetObject<MobilityModel>();
  Ptr<MobilityModel> channelMobility = channelNode->GetObject<MobilityModel>();
  
  if (!vehicleMobility || !channelMobility) {
    return 0.3;
  }
  
  // 计算3D距离
  double distance = vehicleMobility->GetDistanceFrom(channelMobility);
  
  // 确定节点类型
  NodeContainer groundStations = m_nodeManager->GetGroundStationNodes();
  bool isSatellite = (channelId >= static_cast<int>(groundStations.GetN()));
  
  double propagationDelay = 0.0;
  double processingDelay = 0.0;
  double queueingDelay = 0.0;
  
  // 计算传播延迟 (光速传播)
  double speedOfLight = 299792458.0; // 光速 (m/s)
  propagationDelay = distance / speedOfLight;
  
  // 不同链路类型的处理和排队延迟
  if (isSatellite) {
    // 卫星链路额外处理延迟
    processingDelay = 0.005; // 5ms处理延迟
    
    // 基于链路负载的排队延迟 - 这里使用简化模型
    double sinr = CalculateSINR(nodeId, channelId);
    double throughput = CalculateThroughput(sinr, SATELLITE);
    
    // 假设排队延迟与吞吐量成反比关系
    if (throughput > 0.0) {
      queueingDelay = 0.04 * std::exp(-throughput / 30.0);
    } else {
      queueingDelay = 0.04;
    }
    
    // 考虑距离因素
    if (distance > 600000.0) {  // 600km以上
      processingDelay += 0.01;  // 增加10ms处理延迟
    }
  } else {
    // 地面站链路
    processingDelay = 0.002;  // 2ms处理延迟
    
    // 基于链路负载的排队延迟
    double sinr = CalculateSINR(nodeId, channelId);
    double throughput = CalculateThroughput(sinr, GROUND_STATION);
    
    // 假设排队延迟与吞吐量成反比关系
    if (throughput > 0.0) {
      queueingDelay = 0.02 * std::exp(-throughput / 20.0);
    } else {
      queueingDelay = 0.02;
    }
  }
  
  // 计算总延迟 (秒)
  double totalDelay = propagationDelay + processingDelay + queueingDelay;
  
  // 确保延迟值在合理范围内
  totalDelay = std::max(0.001, std::min(totalDelay, 0.5));
  
  return totalDelay;
}
} // namespace ns3
